package com.gulimall.order.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.common.constant.OrderConstant;
import com.common.constant.PayConstant;
import com.common.to.OrderTo;
import com.common.to.SpuInfoTo;
import com.common.to.mq.SeckillOrderTo;
import com.common.utils.R;
import com.gulimall.order.app.OrderController;
import com.gulimall.order.entity.OrderItemEntity;
import com.gulimall.order.entity.PaymentInfoEntity;
import com.gulimall.order.enume.OrderStatusEnum;
import com.gulimall.order.feign.ProductFeignService;
import com.gulimall.order.vo.PayAsyncVo;
import com.gulimall.order.vo.PayVo;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.common.utils.PageUtils;
import com.common.utils.Query;

import com.gulimall.order.dao.OrderDao;
import com.gulimall.order.entity.OrderEntity;
import com.gulimall.order.service.OrderService;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;


@Service("orderService")
public class OrderServiceImpl extends ServiceImpl<OrderDao, OrderEntity> implements OrderService {

    @Resource
    private RabbitTemplate rabbitTemplate;
    @Resource
    private OrderItemServiceImpl orderItemServiceImpl;
    @Resource
    private OrderDao orderDao;
    @Resource
    private PaymentInfoServiceImpl paymentInfoServiceImpl;
    @Resource
    private ProductFeignService productFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<OrderEntity> page = this.page(
                new Query<OrderEntity>().getPage(params),
                new QueryWrapper<OrderEntity>()
        );

        return new PageUtils(page);
    }

    /**
     * 关闭订单
     * @param orderEntity
     */
    @Override
    public void closeOrder(OrderEntity orderEntity) {
        // 获取最新订单，查看订单，如果是新建状态，那么就取消订单，如果是其他状态，说明用户操作了订单，那么就不作修改
        OrderEntity order = this.getById(orderEntity.getId());
        if(order.getStatus().equals(OrderStatusEnum.CREATE_NEW.getCode())){
            // 1、修改状态，设为取消状态
            OrderEntity orderEntity1 = new OrderEntity();
            orderEntity1.setStatus(OrderStatusEnum.CANCLED.getCode());
            orderEntity1.setId(orderEntity.getId());
            this.updateById(orderEntity1);

            // 2、发送库存消息，防止当前消息由于网络原因执行在库存消息之后
            OrderTo orderTo = new OrderTo();
            BeanUtils.copyProperties(orderEntity,orderTo);
            rabbitTemplate.convertAndSend("order-event-exchange","order.release.other",orderTo);
        }
    }

    @Override
    public PayVo getPayVo(String orderSn) {
        PayVo payVo = new PayVo();
        OrderEntity orderInfo = orderDao.selectOne(new QueryWrapper<OrderEntity>().eq("order_sn", orderSn));

        //保留两位小数点，向上取值
        BigDecimal payAmount = orderInfo.getPayAmount().setScale(2, BigDecimal.ROUND_UP);
        payVo.setTotal_amount(payAmount.toString());
        payVo.setOut_trade_no(orderInfo.getOrderSn());

        //查询订单项的数据
        List<OrderItemEntity> orderItemInfo = orderItemServiceImpl.list(
                new QueryWrapper<OrderItemEntity>().eq("order_sn", orderSn));
        OrderItemEntity orderItemEntity = orderItemInfo.get(0);
        payVo.setBody(orderItemEntity.getSkuAttrsVals());

        payVo.setSubject(orderItemEntity.getSkuName());

        return payVo;
    }

    /**
     * 处理支付宝的支付结果、改变订单状态
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public String handlePayResult(PayAsyncVo asyncVo) {

        //1、保存交易流水信息
        PaymentInfoEntity paymentInfo = new PaymentInfoEntity();
        paymentInfo.setOrderSn(asyncVo.getOut_trade_no());
        paymentInfo.setAlipayTradeNo(asyncVo.getTrade_no());
        paymentInfo.setTotalAmount(new BigDecimal(asyncVo.getBuyer_pay_amount()));
        paymentInfo.setSubject(asyncVo.getBody());
        paymentInfo.setPaymentStatus(asyncVo.getTrade_status());
        paymentInfo.setCreateTime(new Date());
        paymentInfo.setCallbackTime(asyncVo.getNotify_time());
        //添加到数据库中
        this.paymentInfoServiceImpl.save(paymentInfo);

        //2、修改订单状态
        //获取当前状态
        String tradeStatus = asyncVo.getTrade_status();

        if (tradeStatus.equals("TRADE_SUCCESS") || tradeStatus.equals("TRADE_FINISHED")) {
            //支付成功状态
            String orderSn = asyncVo.getOut_trade_no(); //获取订单号
            this.baseMapper.updateOrderStatus(orderSn,OrderStatusEnum.PAYED.getCode(), PayConstant.ALIPAY);
        }
        return "success";
    }

    /**
     * 处理秒杀队列的下单操作
     * @param seckillOrderTo
     */
    @Transactional
    @Override
    public void handlerSeckillQueue(SeckillOrderTo seckillOrderTo) {
        // 1、保存订单数据
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOrderSn(seckillOrderTo.getOrderSn());
        orderEntity.setMemberId(seckillOrderTo.getMemberId());
        orderEntity.setCreateTime(new Date());
        orderEntity.setStatus(OrderStatusEnum.CREATE_NEW.getCode());
        orderEntity.setTotalAmount(seckillOrderTo.getSeckillPrice().multiply(BigDecimal.valueOf(seckillOrderTo.getNum())));
        orderEntity.setPayAmount(seckillOrderTo.getSeckillPrice().multiply(BigDecimal.valueOf(seckillOrderTo.getNum())));
        this.save(orderEntity);

        // 2、保存订单项数据
        R r = productFeignService.getSpuInfoBySkuId(seckillOrderTo.getSkuId());
        if(r.getCode() == 0){
            SpuInfoTo spuInfo = r.getData("data", new TypeReference<SpuInfoTo>() {
            });
            OrderItemEntity orderItemEntity = new OrderItemEntity();
            orderItemEntity.setOrderSn(seckillOrderTo.getOrderSn());
            orderItemEntity.setOrderId(orderEntity.getId());
            orderItemEntity.setSkuId(seckillOrderTo.getSkuId());
            orderItemEntity.setSkuQuantity(seckillOrderTo.getNum());
            orderItemEntity.setSpuBrand(spuInfo.getBrandName());
            orderItemEntity.setSpuId(spuInfo.getId());
            orderItemEntity.setSpuName(spuInfo.getSpuName());
            orderItemServiceImpl.save(orderItemEntity);
        }
    }


}